/**
 * Copyright (C) 2013-2014 the original author or authors.
 */
package com.foreveross.bsl.push.repository.custom.impl;

import java.util.Date;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.util.Assert;

import com.foreveross.bsl.push.domain.entity.TagSummary;
import com.foreveross.bsl.push.domain.entity.TagSummary.TagSet;
import com.foreveross.bsl.push.repository.custom.TagSummaryRepositoryCustom;
import com.google.common.collect.Lists;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.WriteResult;

/**
 * xxx
 *
 * @author Wangyi
 * @version v1.0
 *
 * @date 2013-7-15
 *
 */
public class TagSummaryRepositoryImpl implements TagSummaryRepositoryCustom {
	
	private final Logger log = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private MongoTemplate mongoTemplate;

	/* (non-Javadoc)
	 * @see com.foreveross.bsl.push.repository.custom.TagSummaryRepositoryCustom#updateTags(java.lang.String, java.lang.String, java.lang.String[])
	 */
	@Override
	public void updateTags(String appId, String key, String... tagValues) {
		Assert.notNull(appId, "appId can not be null");
		Assert.notNull(key, "key can not be null");
		Assert.notNull(tagValues, "tagValues can not be null");
		
		Criteria appIdCrit=Criteria.where("appId").is(appId);
		long n=this.mongoTemplate.count(Query.query(appIdCrit), TagSummary.class);
		Date updateTime=new Date();
		if(n<=0){
			//新增
			TagSummary ts=new TagSummary();
			ts.setAppId(appId);
			ts.setTags(Lists.newArrayList(new TagSet(key, tagValues)));
			ts.setUpdateTime(updateTime);
			this.mongoTemplate.save(ts);
			return;
		}
		
		Criteria appIdKeyCrit=Criteria.where("appId").is(appId).and("tags.key").is(key);
		n=this.mongoTemplate.count(Query.query(appIdKeyCrit), TagSummary.class);
		Update update=new Update();
		WriteResult wr=null;
		if(n<=0){
			update.push("tags", new TagSet(key, tagValues));
			wr=this.mongoTemplate.updateMulti(Query.query(appIdCrit), update, TagSummary.class);
		}
		else{
			DBObject dbObj=new BasicDBObject();
			dbObj.put("$each", tagValues);
			update.addToSet("tags.$.values", dbObj);
			wr=this.mongoTemplate.updateMulti(Query.query(appIdKeyCrit), update, TagSummary.class);
		}
		log.debug("update count: {}", wr.getN());
		
	}
	
	/* (non-Javadoc)
	 * @see com.foreveross.bsl.push.repository.custom.TagSummaryRepositoryCustom#removeTag(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public boolean removeTags(String appId, String key, String... tagValues) {
		Assert.notNull(appId, "appId can not be null");
		
		Criteria appIdCrit=Criteria.where("appId").is(appId);
		Criteria appIdKeyCrit=Criteria.where("appId").is(appId).and("tags.key").is(key);
		WriteResult wr=null;
		Update update=new Update();
		if(StringUtils.isEmpty(key)){
			//删除该应用的所有标签
			update.unset("tags");
			wr=this.mongoTemplate.updateMulti(Query.query(appIdCrit), update, TagSummary.class);
		}
		else if(!StringUtils.isEmpty(key) && (tagValues==null || tagValues.length==0)){
			//删除该应用的标签键的所有标签值
			//db.tagSummary.update({"_id":"com.xxx.abc"},{$pull:{"tags":{"key":"level"}}})
			DBObject dbObj=new BasicDBObject();
			dbObj.put("key", key);
			update.pull("tags", dbObj);
			wr=this.mongoTemplate.updateMulti(Query.query(appIdKeyCrit), update, TagSummary.class);
		}
		else{
			//删除该应用的标签键的指定标签值
			update.pullAll("tags.$.values", tagValues);
			wr=this.mongoTemplate.updateMulti(Query.query(appIdKeyCrit), update, TagSummary.class);
		}
		
		return wr.getN()>0;
	}
	
	/* (non-Javadoc)
	 * @see com.foreveross.bsl.push.repository.custom.TagSummaryRepositoryCustom#removeTags(java.lang.String)
	 */
	@Override
	public boolean removeAllTags(String appId) {
		return this.removeTags(appId, null);
	}

	/* (non-Javadoc)
	 * @see com.foreveross.bsl.push.repository.custom.TagSummaryRepositoryCustom#removeTagsForAllApps(java.lang.String, java.lang.String[])
	 */
	@Override
	public boolean removeTagsForAllApps(String key, String... tagValues) {
		Criteria appIdKeyCrit=Criteria.where("tags.key").is(key);
		WriteResult wr=null;
		Update update=new Update();
		if(StringUtils.isEmpty(key)){
			//删除所有应用的所有标签
			update.unset("tags");
			wr=this.mongoTemplate.updateMulti(new Query(), update, TagSummary.class);
		}
		else if(!StringUtils.isEmpty(key) && (tagValues==null || tagValues.length==0)){
			//删除所有应用的标签键的所有标签值
			DBObject dbObj=new BasicDBObject();
			dbObj.put("key", key);
			update.pull("tags", dbObj);
			wr=this.mongoTemplate.updateMulti(Query.query(appIdKeyCrit), update, TagSummary.class);
		}
		else{
			//删除所有应用的标签键的指定标签值
			update.pullAll("tags.$.values", tagValues);
			wr=this.mongoTemplate.updateMulti(Query.query(appIdKeyCrit), update, TagSummary.class);
		}
		
		return wr.getN()>0;
	}
}
